package com.atguigu.gmall.order.mq;

import com.atguigu.gmall.common.constant.RabbitConstant;
import com.atguigu.gmall.common.util.JsonUtils;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.payment.PaymentInfo;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.order.service.PaymentInfoService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.rabbitmq.client.Channel;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 监听支付成功的订单，进行后续处理
 */
@Slf4j
@Component
public class OrderPayedListener {


    @Autowired
    OrderInfoService orderInfoService;

    @Autowired
    PaymentInfoService paymentInfoService;

    @Autowired
    RabbitTemplate rabbitTemplate;

    //所有支付成功的订单都在这个队列
    @RabbitListener(queues = RabbitConstant.ORDER_PAYED_QUEUE)
    public void listenDeadOrder(Channel channel, Message message) {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        //1、得到支付成功单内容
        try {
            Map<String, String> data = JsonUtils.converMessageToObject(message, new TypeReference<Map<String, String>>() {
            });

            //2、修改订单状态
            String trade_no = data.get("out_trade_no");
            String trade_status = data.get("trade_status");
            if ("TRADE_SUCCESS".equals(trade_status)) {
                //此次交易成功
                //3、按照这个流水号修改订单状态
                String[] split = trade_no.split("-");
                //4、拿到用户id
                long userId = Long.parseLong(split[split.length - 1]);
                //5、修改订单状态
                orderInfoService.updateOrderStatus(userId, trade_no, OrderStatus.PAID.name(), ProcessStatus.PAID.name());

                //6、保存此次支付流水
                PaymentInfo info = preparePaymentinfo(data, userId);
                paymentInfoService.save(info);


                //7、给库存系统发消息。库存系统收到消息自然就会扣库存
                String wareJson = prepareWareJson(data, userId);
                rabbitTemplate.convertAndSend(RabbitConstant.WARE_ENVENT_EXCHANGE,
                        RabbitConstant.WARE_DEDUCT_STOCK_RK,
                        wareJson);


            }
            channel.basicAck(deliveryTag, false);
        } catch (IOException e) {
            try {
                channel.basicReject(deliveryTag, true);
            } catch (IOException ex) {
                log.error("rabbit连接异常：{}", ex);
            }
        }


    }

    private String prepareWareJson(Map<String, String> data, long userId) {
        Map<String, Object> map = new HashMap<>();

        String trade_no = data.get("out_trade_no");
        //1、查出这个用户的订单信息
        OrderInfo orderInfo = orderInfoService.getOrderByOutTradeNo(trade_no, userId);
        map.put("orderId", orderInfo.getId());
        map.put("consignee", orderInfo.getConsignee());
        map.put("consigneeTel", orderInfo.getConsigneeTel());
        map.put("orderComment", orderInfo.getOrderComment());
        map.put("orderBody", orderInfo.getTradeBody());
        map.put("deliveryAddress", orderInfo.getDeliveryAddress());
        map.put("paymentWay", "2"); //2代表在线支付


        List<OrderDetailTemp> collect = orderInfo.getOrderDetailList()
                .stream().map(item -> {
                    OrderDetailTemp temp = new OrderDetailTemp();
                    BeanUtils.copyProperties(item, temp);
                    return temp;
                }).collect(Collectors.toList());
        map.put("details", collect);

        String json = JsonUtils.parseObjectToJsonStr(map);
        return json;
    }

    @Data
    class OrderDetailTemp {
        private Long skuId;
        private Integer skuNum;
        private String skuName;
    }

    private PaymentInfo preparePaymentinfo(Map<String, String> data, long userId) {
        PaymentInfo info = new PaymentInfo();

        info.setOutTradeNo(data.get("out_trade_no"));
//        info.setOrderId(0L);
        info.setPaymentType("ALIPAY");
        info.setTradeNo(data.get("trade_no"));
        info.setUserId(userId);
        info.setTotalAmount(new BigDecimal(data.get("total_amount")));
        info.setSubject(data.get("subject"));
        info.setPaymentStatus(data.get("trade_status"));
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        try {
            Date date = format.parse(data.get("gmt_create"));
            info.setCreateTime(date);
            Date callback = format.parse(data.get("notify_time"));
            info.setCallbackTime(callback);
        } catch (Exception e) {

        }


        String jsonStr = JsonUtils.parseObjectToJsonStr(data);
        info.setCallbackContent(jsonStr);

        return info;

    }


}
